package com.remon.quartz.controller;

import com.remon.quartz.entity.SimpleTrigger;
import com.remon.quartz.form.BaseJobForm;
import com.remon.quartz.form.JpushJobForm;
import com.remon.quartz.form.RequestJobForm;
import com.remon.quartz.job.BaseJob;
import com.remon.quartz.service.SimpleTriggerService;
import com.remon.quartz.util.Date2CornUtil;
import com.remon.quartz.vo.PageRes;
import github.remonlong.restfulutil.exception.RestfulResultUtil;
import github.remonlong.restfulutil.exception.Result;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 定时器管理
 */
@Slf4j
@RestController
@RequestMapping(value = "/job")
public class JobController {

    //加入Qulifier注解，通过名称注入bean
    @Autowired
    @Qualifier("Scheduler")
    private Scheduler scheduler;

    private final SimpleTriggerService simpleTriggerService;

    @Autowired
    public JobController(SimpleTriggerService simpleTriggerService) {
        this.simpleTriggerService = simpleTriggerService;
    }

    /**
     * 添加url 请求任务
     *
     * @throws Exception
     */
    @PostMapping(value = "/addRestfulJob")
    public Result<String> add(@RequestBody RequestJobForm requestJobForm) throws Exception {
        addJob(requestJobForm);
        return RestfulResultUtil.success();
    }

    /**
     * 添加url 请求任务
     *
     * @throws Exception
     */
    @PostMapping(value = "/addJpushJob")
    public void add(@RequestBody JpushJobForm jobForm) throws Exception {
        addJob(jobForm);
    }

    /**
     * 添加定时器
     *
     * @param jobClassName
     * @param jobGroupName
     * @param cronExpression
     * @throws Exception
     */
    @PostMapping(value = "/addjob")
    public void addjob(@RequestParam(value = "jobClassName") String jobClassName,
                       @RequestParam(value = "jobGroupName") String jobGroupName,
                       @RequestParam(value = "cronExpression") String cronExpression) throws Exception {
        addJob(jobClassName, jobGroupName, cronExpression);
    }

    /**
     * 添加周期性任务
     *
     * @param form @link { RequestJobForm }
     */
    @PostMapping(value = "/addCycleJob")
    public void addCycleJob(RequestJobForm form) throws Exception {
        addJob(form);
    }

    private void addJob(RequestJobForm form) throws Exception {
        // 启动调度器
        scheduler.start();
        Map<String, Object> map = builderJob(form);
        JobDetail jobDetail = (JobDetail) map.get("jobDetail");
        jobDetail.getJobDataMap().put("reqUrl", form.getReqUrl());
        jobDetail.getJobDataMap().put("payload", form.getPayload());
        jobDetail.getJobDataMap().put("reqMethod", form.getReqMethod());
        try {
            scheduler.scheduleJob(jobDetail, (CronTrigger) map.get("jobTrigger"));
        } catch (SchedulerException e) {
            System.out.println("创建定时任务失败" + e);
            throw new Exception("创建定时任务失败");
        }
    }

    /**
     * 极光推送表单
     *
     * @param form
     * @throws Exception
     */
    private void addJob(JpushJobForm form) throws Exception {
        // 启动调度器
        scheduler.start();
        Map<String, Object> map = builderJob(form);
        JobDetail jobDetail = (JobDetail) map.get("jobDetail");
        jobDetail.getJobDataMap().put("payload", form.getPayload());
        jobDetail.getJobDataMap().put("tag", form.getTag());
        jobDetail.getJobDataMap().put("title", form.getTitle());
        try {
            scheduler.scheduleJob(jobDetail, (CronTrigger) map.get("jobTrigger"));
        } catch (SchedulerException e) {
            System.out.println("创建定时任务失败" + e);
            throw new Exception("创建定时任务失败");
        }
    }

    /**
     * 列表
     *
     * @return
     */
    @GetMapping("jobList/{pageNo}/{pageSize}")
    public Result<PageRes<SimpleTrigger>> simpleTriggerResult(@PathVariable("pageNo") Integer pageNo
            , @PathVariable("pageSize") Integer pageSize) {
        PageRes<SimpleTrigger> pageRes = simpleTriggerService.page(pageNo, pageSize);
        return RestfulResultUtil.success(pageRes);
    }

    /**
     * 构建job
     *
     * @param form @link{ BaseJobForm }
     * @return
     * @throws Exception
     */
    private Map<String, Object> builderJob(BaseJobForm form) throws Exception {
        String jobClassName = form.getEnumJob().className;
        String jobGroupName = form.getGroupName();
        String cronExpression = Date2CornUtil.getCron(form.getJobDate());
        //构建job信息
        JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName, jobGroupName).build();
        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName)
                .withSchedule(scheduleBuilder).build();
        Map<String, Object> map = new HashMap<>();
        map.put("jobDetail", jobDetail);
        map.put("jobTrigger", trigger);
        return map;
    }


    private void addJob(String jobClassName, String jobGroupName, String cronExpression) throws Exception {

        // 启动调度器  
        scheduler.start();
        //构建job信息
        JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName, jobGroupName).build();
        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName)
                .withSchedule(scheduleBuilder).build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);

        } catch (SchedulerException e) {
            System.out.println("创建定时任务失败" + e);
            throw new Exception("创建定时任务失败");
        }
    }


    @PostMapping(value = "/pausejob")
    public void pausejob(@RequestParam(value = "jobClassName") String jobClassName, @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
        jobPause(jobClassName, jobGroupName);
    }

    private void jobPause(String jobClassName, String jobGroupName) throws Exception {
        scheduler.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));
    }


    @PostMapping(value = "/resumejob")
    public void resumejob(@RequestParam(value = "jobClassName") String jobClassName, @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
        jobresume(jobClassName, jobGroupName);
    }

    private void jobresume(String jobClassName, String jobGroupName) throws Exception {
        scheduler.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));
    }


    /**
     * 修改任务定时器
     *
     * @param jobClassName
     * @param jobGroupName
     * @param cronExpression
     * @throws Exception
     */
    @PostMapping(value = "/reschedulejob")
    public void rescheduleJob(@RequestParam(value = "jobClassName") String jobClassName,
                              @RequestParam(value = "jobGroupName") String jobGroupName,
                              @RequestParam(value = "cronExpression") String cronExpression) throws Exception {
        jobreschedule(jobClassName, jobGroupName, cronExpression);

    }

    private void jobreschedule(String jobClassName, String jobGroupName, String cronExpression) throws Exception {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            System.out.println("更新定时任务失败" + e);
            throw new Exception("更新定时任务失败");
        }
    }


    /**
     * 删除定时器
     *
     * @param jobClassName
     * @param jobGroupName
     * @throws Exception
     */
    @PostMapping(value = "/deletejob")
    public void deletejob(@RequestParam(value = "jobClassName") String jobClassName, @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
        jobdelete(jobClassName, jobGroupName);
    }

    private void jobdelete(String jobClassName, String jobGroupName) throws Exception {
        scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName, jobGroupName));
        scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName, jobGroupName));
        scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));
    }


    private BaseJob getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (BaseJob) class1.newInstance();
    }


}